package gugga.tasks
{
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	
	import gugga.debug.Assertion;
	import gugga.eventHelpers.EventDescriptor;
	import gugga.eventHelpers.EventRethrower;
	import gugga.eventHelpers.Listener;
	import gugga.tasks.events.ProgressiveTaskEvent;
	import gugga.tasks.events.TaskEvent;
	
	[Event(name="start", type="TaskEvent")]
	[Event(name="interrupted", type="TaskEvent")]
	[Event(name="completed", type="TaskEvent")]
	
	public class AnonymousTask extends EventDispatcher 
		implements IProgressiveTask
	{
		private var mThisObject : *;
		private var mMethod : Function;
		private var mArguments : Array;
		private var mProgress : Number = 0;
		
		private var mTask : ITask;
		
		public function AnonymousTask(aMethod : Function, aArguments : Array, aThisObject : * = null)
		{
			mMethod = aMethod;
			mArguments = aArguments;
			mThisObject = aThisObject;
		}
		
		public function start() : void 
		{
			mTask = ITask(mMethod.apply(mThisObject, mArguments));
			
			Assertion.warningIfEmpty(mTask, "Anonymous task is empty.", this, arguments);
			
			EventRethrower.create(this, mTask, TaskEvent.COMPLETED);
			EventRethrower.create(this, mTask, TaskEvent.INTERRUPTED);
			EventRethrower.create(this, mTask, TaskEvent.START);
			
			if (mTask is IProgressiveTask)
			{
				EventRethrower.create(this, mTask, ProgressiveTaskEvent.PROGRESS);
			}
			else
			{
				mProgress = 0;
				Listener.createSingleTimeListener(
					new EventDescriptor(mTask, TaskEvent.COMPLETED), 
					onTaskCompleted);
			}
			
			
			mTask.start();
		}
	
		public function isRunning() : Boolean 
		{
			return mTask.isRunning();
		}
	
		public function isImmediatelyInterruptable() : Boolean 
		{
			return mTask.isImmediatelyInterruptable();
		}
	
		public function interrupt() : void 
		{
			mTask.interrupt();
		}
		
		public function getProgress() : Number 
		{
			var result : Number = mProgress;
			if (mTask is IProgressiveTask)
			{
				result = IProgressiveTask(mTask).getProgress();
			}
			return result;
		}
		
		private function onTaskCompleted(aEvent : TaskEvent) : void 
		{
			mProgress = 100;
			dispatchEvent(new ProgressiveTaskEvent(ProgressiveTaskEvent.PROGRESS, 100, 100, 100));
		}
	}
}